package com.gzc.just.play.last.war.loginserver.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 认证服务
 * 处理用户登录、注册、令牌验证等
 */
@Service
public class AuthService {
    private static final Logger logger = LoggerFactory.getLogger(AuthService.class);
    
    // 用户信息缓存（用户名 -> 用户信息）
    private final Map<String, UserInfo> userCache = new ConcurrentHashMap<>();
    
    // 邮箱到用户名的映射
    private final Map<String, String> emailToUsername = new ConcurrentHashMap<>();
    
    // 在线用户（用户ID -> 登录信息）
    private final Map<Long, LoginSession> loginSessions = new ConcurrentHashMap<>();
    
    // 密码重置请求（邮箱 -> 重置信息）
    private final Map<String, PasswordResetInfo> resetRequests = new ConcurrentHashMap<>();
    
    // 用户ID生成器
    private final AtomicLong userIdGenerator = new AtomicLong(100000);
    
    @PostConstruct
    public void init() {
        // 初始化一些示例用户
        initSampleUsers();
        
        logger.info("AuthService initialized with {} users", userCache.size());
    }
    
    /**
     * 初始化示例用户
     */
    private void initSampleUsers() {
        // 创建一些示例用户
        createUser("testuser", "testpass", "testuser@example.com");
        createUser("alice", "alice123", "alice@example.com");
        createUser("bob", "bob123", "bob@example.com");
        createUser("charlie", "charlie123", "charlie@example.com");
    }
    
    /**
     * 创建用户
     */
    private void createUser(String username, String password, String email) {
        Long userId = userIdGenerator.incrementAndGet();
        UserInfo userInfo = new UserInfo(userId, username, password, email);
        userCache.put(username, userInfo);
        emailToUsername.put(email, username);
    }
    
    /**
     * 用户信息类
     */
    public static class UserInfo {
        private final Long userId;
        private final String username;
        private final String password;
        private final String email;
        private final long createTime;
        private volatile long lastLoginTime;
        private volatile int loginCount;
        
        public UserInfo(Long userId, String username, String password, String email) {
            this.userId = userId;
            this.username = username;
            this.password = password;
            this.email = email;
            this.createTime = System.currentTimeMillis();
            this.lastLoginTime = 0;
            this.loginCount = 0;
        }
        
        // Getters
        public Long getUserId() { return userId; }
        public String getUsername() { return username; }
        public String getPassword() { return password; }
        public String getEmail() { return email; }
        public long getCreateTime() { return createTime; }
        public long getLastLoginTime() { return lastLoginTime; }
        public int getLoginCount() { return loginCount; }
        
        // Setters
        public void setLastLoginTime(long lastLoginTime) { this.lastLoginTime = lastLoginTime; }
        public void incrementLoginCount() { this.loginCount++; }
    }
    
    /**
     * 登录会话类
     */
    public static class LoginSession {
        private final Long userId;
        private final String username;
        private final String token;
        private final long loginTime;
        private volatile long lastActiveTime;
        private final String sessionId;
        
        public LoginSession(Long userId, String username, String token) {
            this.userId = userId;
            this.username = username;
            this.token = token;
            this.loginTime = System.currentTimeMillis();
            this.lastActiveTime = this.loginTime;
            this.sessionId = UUID.randomUUID().toString();
        }
        
        // Getters
        public Long getUserId() { return userId; }
        public String getUsername() { return username; }
        public String getToken() { return token; }
        public long getLoginTime() { return loginTime; }
        public long getLastActiveTime() { return lastActiveTime; }
        public String getSessionId() { return sessionId; }
        
        // Setters
        public void setLastActiveTime(long lastActiveTime) { this.lastActiveTime = lastActiveTime; }
    }
    
    /**
     * 密码重置信息类
     */
    public static class PasswordResetInfo {
        private final String email;
        private final String verificationCode;
        private final long requestTime;
        private final String token;
        private boolean verified;
        
        public PasswordResetInfo(String email, String verificationCode, String token) {
            this.email = email;
            this.verificationCode = verificationCode;
            this.requestTime = System.currentTimeMillis();
            this.token = token;
            this.verified = false;
        }
        
        // Getters
        public String getEmail() { return email; }
        public String getVerificationCode() { return verificationCode; }
        public long getRequestTime() { return requestTime; }
        public String getToken() { return token; }
        public boolean isVerified() { return verified; }
        
        // Setters
        public void setVerified(boolean verified) { this.verified = verified; }
    }
    
    /**
     * 认证用户
     */
    public Map<String, Object> authenticate(String username, String password) {
        Map<String, Object> result = new HashMap<>();
        
        // 查找用户
        UserInfo userInfo = userCache.get(username);
        if (userInfo == null) {
            result.put("success", false);
            result.put("message", "User not found");
            return result;
        }
        
        // 验证密码
        if (!userInfo.getPassword().equals(password)) {
            result.put("success", false);
            result.put("message", "Invalid password");
            return result;
        }
        
        // 生成令牌
        String token = generateToken(userInfo.getUserId());
        
        // 更新登录信息
        userInfo.setLastLoginTime(System.currentTimeMillis());
        userInfo.incrementLoginCount();
        
        // 创建登录会话
        LoginSession loginSession = new LoginSession(userInfo.getUserId(), username, token);
        loginSessions.put(userInfo.getUserId(), loginSession);
        
        // 返回成功结果
        result.put("success", true);
        result.put("message", "Login successful");
        result.put("userId", userInfo.getUserId());
        result.put("username", userInfo.getUsername());
        result.put("email", userInfo.getEmail());
        result.put("token", token);
        result.put("loginTime", loginSession.getLoginTime());
        result.put("sessionId", loginSession.getSessionId());
        result.put("loginCount", userInfo.getLoginCount());
        
        logger.info("User {} authenticated successfully", username);
        return result;
    }
    
    /**
     * 用户登出
     */
    public boolean logout(Long userId) {
        LoginSession loginSession = loginSessions.remove(userId);
        if (loginSession != null) {
            logger.info("User {} logged out successfully", userId);
            return true;
        }
        
        logger.warn("Logout failed for user: {}", userId);
        return false;
    }
    
    /**
     * 注册用户
     */
    public Map<String, Object> register(String username, String password, String email) {
        Map<String, Object> result = new HashMap<>();
        
        // 检查用户名是否已存在
        if (userCache.containsKey(username)) {
            result.put("success", false);
            result.put("message", "Username already exists");
            return result;
        }
        
        // 检查邮箱是否已存在
        if (emailToUsername.containsKey(email)) {
            result.put("success", false);
            result.put("message", "Email already registered");
            return result;
        }
        
        // 创建用户
        Long userId = userIdGenerator.incrementAndGet();
        UserInfo userInfo = new UserInfo(userId, username, password, email);
        userCache.put(username, userInfo);
        emailToUsername.put(email, username);
        
        // 返回成功结果
        result.put("success", true);
        result.put("message", "Registration successful");
        result.put("userId", userId);
        result.put("username", username);
        result.put("email", email);
        
        logger.info("User {} registered successfully", username);
        return result;
    }
    
    /**
     * 验证令牌
     */
    public Map<String, Object> validateToken(String token) {
        Map<String, Object> result = new HashMap<>();
        
        // 查找令牌对应的会话
        for (LoginSession session : loginSessions.values()) {
            if (token.equals(session.getToken())) {
                // 更新最后活动时间
                session.setLastActiveTime(System.currentTimeMillis());
                
                // 返回验证结果
                result.put("valid", true);
                result.put("message", "Token valid");
                result.put("userId", session.getUserId());
                result.put("username", session.getUsername());
                result.put("sessionId", session.getSessionId());
                result.put("loginTime", session.getLoginTime());
                result.put("lastActiveTime", session.getLastActiveTime());
                
                return result;
            }
        }
        
        // 令牌无效
        result.put("valid", false);
        result.put("message", "Invalid or expired token");
        
        return result;
    }
    
    /**
     * 请求密码重置
     */
    public Map<String, Object> requestPasswordReset(String emailOrUsername) {
        Map<String, Object> result = new HashMap<>();
        
        // 查找用户
        UserInfo userInfo = userCache.get(emailOrUsername);
        if (userInfo == null) {
            // 尝试通过邮箱查找
            String username = emailToUsername.get(emailOrUsername);
            if (username == null) {
                result.put("success", false);
                result.put("message", "User not found");
                return result;
            }
            userInfo = userCache.get(username);
        }
        
        // 生成验证码和重置令牌
        String verificationCode = generateVerificationCode();
        String resetToken = UUID.randomUUID().toString();
        
        // 保存重置信息
        PasswordResetInfo resetInfo = new PasswordResetInfo(userInfo.getEmail(), verificationCode, resetToken);
        resetRequests.put(userInfo.getEmail(), resetInfo);
        
        // 在实际实现中，这里应该发送验证码到用户邮箱
        // sendVerificationCodeEmail(userInfo.getEmail(), verificationCode);
        
        // 返回成功结果
        result.put("success", true);
        result.put("message", "Password reset code sent to email");
        result.put("email", userInfo.getEmail()); // 实际实现中可能不返回邮箱
        result.put("resetToken", resetToken);
        
        logger.info("Password reset requested for user: {}", userInfo.getUsername());
        return result;
    }
    
    /**
     * 验证重置码
     */
    public Map<String, Object> verifyResetCode(String email, String code) {
        Map<String, Object> result = new HashMap<>();
        
        // 查找重置请求
        PasswordResetInfo resetInfo = resetRequests.get(email);
        if (resetInfo == null) {
            result.put("success", false);
            result.put("message", "Reset request not found");
            return result;
        }
        
        // 检查验证码
        if (!code.equals(resetInfo.getVerificationCode())) {
            result.put("success", false);
            result.put("message", "Invalid verification code");
            return result;
        }
        
        // 检查是否过期（示例：30分钟内有效）
        long elapsed = System.currentTimeMillis() - resetInfo.getRequestTime();
        if (elapsed > 30 * 60 * 1000) {
            resetRequests.remove(email);
            result.put("success", false);
            result.put("message", "Verification code expired");
            return result;
        }
        
        // 标记为已验证
        resetInfo.setVerified(true);
        
        // 返回成功结果
        result.put("success", true);
        result.put("message", "Verification code valid");
        result.put("resetToken", resetInfo.getToken());
        
        return result;
    }
    
    /**
     * 重置密码
     */
    public Map<String, Object> resetPassword(String email, String code, String newPassword) {
        Map<String, Object> result = new HashMap<>();
        
        // 查找重置请求
        PasswordResetInfo resetInfo = resetRequests.get(email);
        if (resetInfo == null) {
            result.put("success", false);
            result.put("message", "Reset request not found");
            return result;
        }
        
        // 检查验证码
        if (!code.equals(resetInfo.getVerificationCode()) || !resetInfo.isVerified()) {
            result.put("success", false);
            result.put("message", "Invalid or unverified verification code");
            return result;
        }
        
        // 查找用户
        String username = emailToUsername.get(email);
        if (username == null) {
            result.put("success", false);
            result.put("message", "User not found");
            return result;
        }
        
        UserInfo userInfo = userCache.get(username);
        
        // 更新密码
        UserInfo newUserInfo = new UserInfo(userInfo.getUserId(), username, newPassword, email);
        newUserInfo.setLastLoginTime(userInfo.getLastLoginTime());
        
        // 这里需要创建新的UserInfo对象，因为password是final的
        // 实际实现中可以使用不同的设计
        
        userCache.put(username, newUserInfo);
        
        // 清除重置请求
        resetRequests.remove(email);
        
        // 清除所有登录会话
        loginSessions.remove(userInfo.getUserId());
        
        // 返回成功结果
        result.put("success", true);
        result.put("message", "Password reset successfully");
        
        logger.info("Password reset successfully for user: {}", username);
        return result;
    }
    
    /**
     * 生成令牌
     */
    private String generateToken(Long userId) {
        // 在实际实现中，应该使用JWT或其他安全的令牌生成机制
        // 这里只是示例，生成一个简单的令牌
        return "token_" + userId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }
    
    /**
     * 生成验证码
     */
    private String generateVerificationCode() {
        // 生成6位数字验证码
        return String.valueOf((int)(Math.random() * 900000) + 100000);
    }
    
    /**
     * 获取在线用户数量
     */
    public int getOnlineUserCount() {
        return loginSessions.size();
    }
    
    /**
     * 获取总用户数量
     */
    public int getTotalUserCount() {
        return userCache.size();
    }
}